#include "CommandDefine.h"
#include "service.grpc.pb.h"
#include <grpcpp/grpcpp.h>

using namespace std;

namespace gitstore {

void createDataset(CommandLineParser *parser) {
    GitStoreGrpc::RequestCreateDataset request;
    if ( !parser->has("dataset") ) {
        printf("param '%s' requested", "dataset");
        return;
    }
    request.set_dataset_name(parser->get<string>("dataset"));
    request.set_dataset_note("");
    request.set_dataset_type(parser->get<int>("type"));
    auto branch = parser->get<string>("branch");
    if ( !parser->has("branch") ) {
        printf("param '%s' requested", "branch");
        return;
    }
    request.set_branch_name(parser->get<string>("branch"));
    request.set_branch_note("");
    if ( !parser->has("key") ) {
        printf("param '%s' requested", "key");
        return;
    }
    cout<<parser->get<string>("key")<<endl;
    request.add_keys(parser->get<string>("key"));
    if ( !parser->has("value") ) {
        printf("param '%s' requested", "value");
        return;
    }
    request.add_values(parser->get<string>("value"));

    string url = parser->get<string>("host") + ":" + parser->get<string>("port");
    GitStoreGrpc::ResponseCreateDataset response;
    auto stub = GitStoreGrpc::GitStoreGrpcService::NewStub(grpc::CreateChannel(url, grpc::InsecureChannelCredentials()));
    grpc::ClientContext context;
    auto res = stub->CreateDataset(&context, request, &response);
    printf("grpc code: %d\nreturn code: %d,\nmessage: '%s'\ndata: \n\tbranch revision is %d\n\tdataset revision is %d\n", res.error_code(), response.release_code()->code(),
           response.release_code()->release_msg()->c_str(), response.revision_branch(), response.revision_dataset());
}

void putKey(CommandLineParser *parser) {
    GitStoreGrpc::RequestPutKey request;
    if ( !parser->has("dataset") ) {
        printf("param '%s' requested", "dataset");
        return;
    }
    request.set_dataset_name(parser->get<string>("dataset"));
    auto branch = parser->get<string>("branch");
    if ( !parser->has("branch") ) {
        printf("param '%s' requested", "branch");
        return;
    }
    request.set_branch_name(parser->get<string>("branch"));
    if ( !parser->has("key") ) {
        printf("param '%s' requested", "key");
        return;
    }
    request.set_key(parser->get<string>("key"));
    if ( !parser->has("value") ) {
        printf("param '%s' requested", "value");
        return;
    }
    request.set_value(parser->get<string>("value"));
//    if ( !parser->has("version") ) {
//        printf("param '%s' requested", "version");
//        return;
//    }
//    request.set_version_pre(parser->get<string>("version"));
    request.set_note("");
    request.set_type(parser->get<int>("type"));
    if ( !parser->has("size") ) {
        printf("param '%s' requested", "size");
        return;
    }
    request.set_size(parser->get<int>("size"));
    if ( !parser->has("revision") ) {
        printf("param '%s' requested", "revision");
        return;
    }
    request.set_revision_branch(parser->get<int>("revision"));
    string url = parser->get<string>("host") + ":" + parser->get<string>("port");
    GitStoreGrpc::ResponsePutKey response;
    auto stub = GitStoreGrpc::GitStoreGrpcService::NewStub(grpc::CreateChannel(url, grpc::InsecureChannelCredentials()));
    grpc::ClientContext context;
    auto res = stub->PutKey(&context, request, &response);
    printf("grpc code: %d\nreturn code: %d,\nmessage: '%s'\ndata: \n\tbranch revision is %d\n", res.error_code(), response.mutable_code()->code(),
           response.mutable_code()->mutable_msg()->c_str(), response.revision_branch());
}

void listDataset(CommandLineParser *parser) {
    GitStoreGrpc::RequestListDataset request;

    string url = parser->get<string>("host") + ":" + parser->get<string>("port");
    GitStoreGrpc::ResponseListDataset response;
    auto stub = GitStoreGrpc::GitStoreGrpcService::NewStub(grpc::CreateChannel(url, grpc::InsecureChannelCredentials()));
    grpc::ClientContext context;
    auto res = stub->ListDataset(&context, request, &response);
    string data;
    data.reserve(response.datasets().size()*10);
    data.push_back('[');
    int count = 0;
    for ( auto &ds_name : response.datasets() ) {
        ++count;
        if ( count < 10 ) {
            data.append(ds_name);
            data.push_back(',');
        } else {
            data.append("...More");
            break;
        }
    }
    data.push_back(']');
    data.push_back('(');
    data.append(std::to_string(response.datasets().size()));
    data.push_back(')');
    printf("grpc code: %d\nreturn code: %d,\nmessage: '%s'\ndata: '%s'\n", int(res.error_code()), int(response.mutable_code()->code()), response.mutable_code()->mutable_msg()->c_str(),data.c_str());
}

void listDatasetBranches(CommandLineParser *parser) {
    GitStoreGrpc::RequestListDatasetBranches request;
    if ( !parser->has("dataset") ) {
        printf("param '%s' requested", "dataset");
        return;
    }
    request.set_dataset_name(parser->get<string>("dataset"));
    string url = parser->get<string>("host") + ":" + parser->get<string>("port");
    GitStoreGrpc::ResponseListDatasetBranches response;
    auto stub = GitStoreGrpc::GitStoreGrpcService::NewStub(grpc::CreateChannel(url, grpc::InsecureChannelCredentials()));
    grpc::ClientContext context;
    auto res = stub->ListDatasetBranches(&context, request, &response);
    string data;
    data.reserve(response.branches().size()*10);
    data.push_back('[');
    int count = 0;
    for ( auto &ds_name : response.branches() ) {
        ++count;
        if ( count < 10 ) {
            data.append(ds_name);
            data.push_back(',');
        } else {
            data.append("...More");
            break;
        }
    }
    data.push_back(']');
    data.push_back('(');
    data.append(std::to_string(response.branches().size()));
    data.push_back(')');
    printf("grpc code: %d\nreturn code: %d,\nmessage: '%s'\ndata: '%s'\n", int(res.error_code()), int(response.mutable_code()->code()), response.mutable_code()->mutable_msg()->c_str(),data.c_str());
}

void listDatasetKeysByBranch(CommandLineParser *parser) {
    GitStoreGrpc::RequestListDatasetKeysByBranch request;
    if ( !parser->has("dataset") ) {
        printf("param '%s' requested", "dataset");
        return;
    }
    request.set_dataset_name(parser->get<string>("dataset"));
    if ( !parser->has("branch") ) {
        printf("param '%s' requested", "branch");
        return;
    }
    request.set_branch_name(parser->get<string>("branch"));
    string url = parser->get<string>("host") + ":" + parser->get<string>("port");
    GitStoreGrpc::ResponseListDatasetKeysByBranch response;
    auto stub = GitStoreGrpc::GitStoreGrpcService::NewStub(grpc::CreateChannel(url, grpc::InsecureChannelCredentials()));
    grpc::ClientContext context;
    auto res = stub->ListDatasetKeysByBranch(&context, request, &response);
    string data;
    data.reserve(response.keys().size()*10);
    data.push_back('[');
    int count = 0;
    for ( auto &ds_name : response.keys() ) {
        ++count;
        if ( count < 10 ) {
            data.append(ds_name);
            data.push_back(',');
        } else {
            data.append("...More");
            break;
        }
    }
    data.push_back(']');
    data.push_back('(');
    data.append(std::to_string(response.keys().size()));
    data.push_back(')');
    printf("grpc code: %d\nreturn code: %d,\nmessage: '%s'\ndata: \n\tkeys are '%s'\n\tbranch revision is %d\n", int(res.error_code()), int(response.mutable_code()->code()),
           response.mutable_code()->mutable_msg()->c_str(),data.c_str(),response.revision_branch());
}

void listDatasetKeysByVersion(CommandLineParser *parser) {
    GitStoreGrpc::RequestListDatasetKeysByVersion request;
    if ( !parser->has("dataset") ) {
        printf("param '%s' requested", "dataset");
        return;
    }
    request.set_dataset_name(parser->get<string>("dataset"));
    if ( !parser->has("version") ) {
        printf("param '%s' requested", "version");
        return;
    }
    request.set_version(parser->get<string>("version"));
    string url = parser->get<string>("host") + ":" + parser->get<string>("port");
    GitStoreGrpc::ResponseListDatasetKeysByVersion response;
    auto stub = GitStoreGrpc::GitStoreGrpcService::NewStub(grpc::CreateChannel(url, grpc::InsecureChannelCredentials()));
    grpc::ClientContext context;
    auto res = stub->ListDatasetKeysByVersion(&context, request, &response);
    string data;
    data.reserve(response.keys().size()*10);
    data.push_back('[');
    int count = 0;
    for ( auto &ds_name : response.keys() ) {
        ++count;
        if ( count < 10 ) {
            data.append(ds_name);
            data.push_back(',');
        } else {
            data.append("...More");
            break;
        }
    }
    data.push_back(']');
    data.push_back('(');
    data.append(std::to_string(response.keys().size()));
    data.push_back(')');
    printf("grpc code: %d\nreturn code: %d,\nmessage: '%s'\ndata: '%s'\n", int(res.error_code()), int(response.mutable_code()->code()), response.mutable_code()->mutable_msg()->c_str(),data.c_str());
}

void branchDataset(CommandLineParser *parser) {
    GitStoreGrpc::RequestBranchDataset request;
    if ( !parser->has("dataset") ) {
        printf("param '%s' requested", "dataset");
        return;
    }
    request.set_dataset_name(parser->get<string>("dataset"));
    if ( !parser->has("branch") ) {
        printf("param '%s' requested", "branch");
        return;
    }
    request.set_refer_branch_name(parser->get<string>("branch"));
    if ( !parser->has("new_branch") ) {
        printf("param '%s' requested", "new_branch");
        return;
    }
    request.set_new_branch_name(parser->get<string>("new_branch"));
    if ( !parser->has("revision") ) {
        printf("param '%s' requested", "revision");
        return;
    }
    request.set_revision_refer_branch(parser->get<int>("revision"));
    request.set_new_branch_note(parser->get<string>("branch_note"));
    string url = parser->get<string>("host") + ":" + parser->get<string>("port");
    GitStoreGrpc::ResponseBranchDataset response;
    auto stub = GitStoreGrpc::GitStoreGrpcService::NewStub(grpc::CreateChannel(url, grpc::InsecureChannelCredentials()));
    grpc::ClientContext context;
    auto res = stub->BranchDataset(&context, request, &response);
    printf("grpc code: %d\nreturn code: %d,\nmessage: '%s'\ndata: \n\trevision is %d\n", int(res.error_code()),
           int(response.mutable_code()->code()), response.mutable_code()->mutable_msg()->c_str(), response.revision_new_branch());
}

void getKeyByBranch(CommandLineParser *parser) {
    GitStoreGrpc::RequestGetKeyByBranch request;
    if ( !parser->has("dataset") ) {
        printf("param '%s' requested", "dataset");
        return;
    }
    request.set_dataset_name(parser->get<string>("dataset"));
    if ( !parser->has("branch") ) {
        printf("param '%s' requested", "branch");
        return;
    }
    request.set_branch_name(parser->get<string>("branch"));

    if ( !parser->has("key") ) {
        printf("param '%s' requested", "key");
        return;
    }
    request.set_key(parser->get<string>("key"));

    string url = parser->get<string>("host") + ":" + parser->get<string>("port");
    GitStoreGrpc::ResponseGetKeyByBranch response;
    auto stub = GitStoreGrpc::GitStoreGrpcService::NewStub(grpc::CreateChannel(url, grpc::InsecureChannelCredentials()));
    grpc::ClientContext context;
    auto res = stub->GetKeyByBranch(&context, request, &response);
    if ( response.type() == 0 ) {
        printf("grpc code: %d\nreturn code: %d,\nmessage: '%s'\ndata: \n\tcontent is '%s'\n\tbranch revision is %d\n",
               int(res.error_code()), int(response.mutable_code()->code()), response.mutable_code()->mutable_msg()->c_str(),
               response.value().c_str(), response.revision_branch());
    } else {
        printf("grpc code: %d\nreturn code: %d,\nmessage: '%s'\ndata: \n\tBlob, size is %lu\n\tbranch revision is %d\n",
               int(res.error_code()), int(response.mutable_code()->code()), response.mutable_code()->mutable_msg()->c_str(),
               response.size(), response.revision_branch());
    }
}

void getKeyByVersion(CommandLineParser *parser) {
    GitStoreGrpc::RequestGetKeyByVersion request;
    if ( !parser->has("dataset") ) {
        printf("param '%s' requested", "dataset");
        return;
    }
    request.set_dataset_name(parser->get<string>("dataset"));
    if ( !parser->has("version") ) {
        printf("param '%s' requested", "version");
        return;
    }
    request.set_version(parser->get<string>("version"));

    string url = parser->get<string>("host") + ":" + parser->get<string>("port");
    GitStoreGrpc::ResponseGetKeyByVersion response;
    auto stub = GitStoreGrpc::GitStoreGrpcService::NewStub(grpc::CreateChannel(url, grpc::InsecureChannelCredentials()));
    grpc::ClientContext context;
    auto res = stub->GetKeyByVersion(&context, request, &response);
    if ( response.type() == 0 ) {
        printf("grpc code: %d\nreturn code: %d,\nmessage: '%s'\ndata: '%s'\n", int(res.error_code()), int(response.mutable_code()->code()), response.mutable_code()->mutable_msg()->c_str(), response.value().c_str());
    } else {
        printf("grpc code: %d\nreturn code: %d,\nmessage: '%s'\ndata: Blob, size is %lu\n", int(res.error_code()), int(response.mutable_code()->code()), response.mutable_code()->mutable_msg()->c_str(), response.size());
    }
}

void diffKeysByBranch(CommandLineParser *parser) {
    GitStoreGrpc::RequestDiffKeysByBranch request;
    if ( !parser->has("dataset") ) {
        printf("param '%s' requested", "dataset");
        return;
    }
    request.set_dataset_name(parser->get<string>("dataset"));
    if ( !parser->has("branch") ) {
        printf("param '%s' requested", "branch");
        return;
    }
    request.set_branch_name1(parser->get<string>("branch"));
    if ( !parser->has("new_branch") ) {
        printf("param '%s' requested", "new_branch");
        return;
    }
    request.set_branch_name2(parser->get<string>("new_branch"));
    string url = parser->get<string>("host") + ":" + parser->get<string>("port");
    GitStoreGrpc::ResponseDiffKeysByBranch response;
    auto stub = GitStoreGrpc::GitStoreGrpcService::NewStub(grpc::CreateChannel(url, grpc::InsecureChannelCredentials()));
    grpc::ClientContext context;
    auto res = stub->DiffKeysByBranch(&context, request, &response);
    string data;
    data.reserve(response.keys().size()*10);
    data.push_back('[');
    int count = 0;
    for ( auto &ds_name : response.keys() ) {
        ++count;
        if ( count < 10 ) {
            data.append(ds_name);
            data.push_back(',');
        } else {
            data.append("...More");
            break;
        }
    }
    data.push_back(']');
    data.push_back('(');
    data.append(std::to_string(response.keys().size()));
    data.push_back(')');
    printf("grpc code: %d\nreturn code: %d,\nmessage: '%s'\ndata: \n\tdifferent keys are '%s'\n\tbranch1 revision is %d\n\tbranch2 revision is %d\n",
           int(res.error_code()), int(response.mutable_code()->code()),
           response.mutable_code()->mutable_msg()->c_str(),data.c_str(),
           response.revision_branch1(), response.revision_branch2());
}

void diffKeysByVersion(CommandLineParser *parser) {
    GitStoreGrpc::RequestDiffKeysByVersion request;
    if ( !parser->has("dataset") ) {
        printf("param '%s' requested", "dataset");
        return;
    }
    request.set_dataset_name(parser->get<string>("dataset"));
    if ( !parser->has("version") ) {
        printf("param '%s' requested", "version");
        return;
    }
    request.set_version1(parser->get<string>("version"));
    if ( !parser->has("refer_version") ) {
        printf("param '%s' requested", "refer_version");
        return;
    }
    request.set_version2(parser->get<string>("refer_version"));
    string url = parser->get<string>("host") + ":" + parser->get<string>("port");
    GitStoreGrpc::ResponseDiffKeysByVersion response;
    auto stub = GitStoreGrpc::GitStoreGrpcService::NewStub(grpc::CreateChannel(url, grpc::InsecureChannelCredentials()));
    grpc::ClientContext context;
    auto res = stub->DiffKeysByVersion(&context, request, &response);
    string data;
    data.reserve(response.keys().size()*10);
    data.push_back('[');
    int count = 0;
    for ( auto &ds_name : response.keys() ) {
        ++count;
        if ( count < 10 ) {
            data.append(ds_name);
            data.push_back(',');
        } else {
            data.append("...More");
            break;
        }
    }
    data.push_back(']');
    data.push_back('(');
    data.append(std::to_string(response.keys().size()));
    data.push_back(')');
    printf("grpc code: %d\nreturn code: %d,\nmessage: '%s'\ndata: '%s'\n", int(res.error_code()), int(response.mutable_code()->code()), response.mutable_code()->mutable_msg()->c_str(),data.c_str());
}

}


